package com.pattern.proxy.v8;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Random;

/**
 * 如果想让LogProxy重用，不仅可以代理Tank,还可以代理任何其它的类型[Object]
 * 怎么办？？？
 * 本质：分离代理行为与被代理对象
 * 使用JDK的动态代理
 * <p>
 * 前面写的静态代理：是因为你知道代理的是move方法，所以代理内部调用的move方法
 * 如果是需要代理其它的，是不确定是什么方法的
 * <p>
 * 使用JDK动态代理
 */
public class Tank implements Movable {
    @Override
    public void move() {
        System.out.println("tank moving ");
        try {
            Thread.sleep(new Random().nextInt(10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        Tank tank = new Tank();

        /*
        参数解释：
            1. Tank.class.getClassLoader() 作用： 生产的代理对象使用哪个类加载器加载到内存
            2. new Class[]{Movable.class}  被代理对象实现那些接口（Tank实现的接口）
            3. new InvocationHandler() 调用处理器，指被代理对象那个方法被调用时我们怎么做处理；即Tank类的move方法

         */
        Movable m = (Movable) Proxy.newProxyInstance(Tank.class.getClassLoader(),
                new Class[]{Movable.class}, // 也可以使用 Tank.class.getInterfaces()
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
                        System.out.println("method " + method.getName() + " start");
                        Object o = method.invoke(tank, args);
                        System.out.println("method " + method.getName() + " end");
                        return null;
                    }
                }
        );
        m.move();
    }
}

interface Movable {
    void move();
}
